package fr.inserm.um915.jimpute.model;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import com.sleepycat.je.Transaction;

public class GuessBuild
	{
	private static final Logger LOG=Logger.getLogger("fr.inserm.um915.jimpute");
	
	static class Choice implements Comparable<Choice>
		{
		Build build;
		int firstBaseIndex;
		int match=0;
		Set<String> representants=new HashSet<String>();
		Choice(Build build,int firstBaseIndex)
			{
			this.build=build;
			this.firstBaseIndex=firstBaseIndex;
			}
		
		@Override
		public int compareTo(Choice o)
			{
			return o.match-this.match;
			}
		
		@Override
		public String toString() {
			return build.name()+"\t"+"+"+firstBaseIndex+"\tHits:"+match+"\t"+representants;
			}
		}
	
	private Model model;
	private GuessBuild()
		{
		
		}
	
	void close()
		{
		model.close();
		}
	
	
	void run(Transaction txn,String filename,BufferedReader in) throws IOException
		{
		int count_never_matched=0;
		List<Choice> choices=new ArrayList<Choice>();
		List<String> neverMatched=new ArrayList<String>();
		for(Build b:Build.values())
			{
			choices.add(new Choice(b,0));
			choices.add(new Choice(b,1));
			}
		Pattern rsPattern=Pattern.compile("rs[0-9]+");
		Pattern tab=Pattern.compile("[\t]");
		String line;
		while((line=in.readLine())!=null)
			{
			if(line.startsWith("#") || line.isEmpty()) continue;
			String tokens[]=tab.split(line);
			if(tokens.length<3)
				{
				System.err.println("expected at least 3 tokens "+line);
				continue;
				}
			Chromosome chromosome=Chromosome.parse(tokens[0]);
			if(chromosome==null)
				{
				System.err.println("unknown chromosome "+line);
				continue;
				}
			
			int position=0;
			try
				{
				position=Integer.parseInt(tokens[1]);
				}
			catch(NumberFormatException err)
				{
				System.err.println("Bad position in "+line);
				++count_never_matched;
				continue;
				}
			
			/* is it a rs## ? */
			if(!rsPattern.matcher(tokens[2]).matches())
				{
				System.err.println("Bad rs## in "+line);
				++count_never_matched;
				continue;
				}
				
			int rsId=Integer.parseInt(tokens[2].substring(2));
				
			
			List<BuildChromPosition> positions=model.findRsPositionsByName(txn, rsId);
			if(positions==null) positions=Collections.emptyList();
			
			boolean found=false;
			for(Choice choice:choices)
				{
				for(BuildChromPosition bcp:positions)
					{
					if((int)bcp.getBuildIdx()!=choice.build.ordinal()) continue;
					if(chromosome.ordinal()!=(int)bcp.getChromosomeIdx()) continue;
					int posdbsnp0= bcp.getPosition();
					int posX=position;
					if(choice.firstBaseIndex==1)
						{
						posX--;
						}
					if(posX==posdbsnp0)
						{
						if(choice.representants.size()<10)
							{
							choice.representants.add(tokens[2]);
							}
						choice.match++;
						found=true;
						}
					}
				}
			if(!found)
				{
				if(neverMatched.size()<10)
					{
					neverMatched.add(line);
					}
				count_never_matched++;
				}
			}
		Collections.sort(choices);
		for(Choice c:choices)
			{
			System.out.println(c);
			}
		System.out.println("lines never matched:"+count_never_matched);
		for(String s:neverMatched)
			{
			System.out.println(s);
			}
		}
	
	public static void main(String[] args) throws Exception
		{
		File dbHome=null;
		int optind=0;
		while(optind<args.length)
				{
				if(args[optind].equals("-h"))
					{
					System.out.println("-d (berkeleydb) directory");
					System.out.println("expected input: CHROM\\tPOS \\tRS###");
					return;
					}
				else if(args[optind].equals("-d"))
					{
					dbHome=new File(args[++optind]);
					}
				else if(args[optind].equals("--"))
					{
					optind++;
					break;
					}
				else if(args[optind].startsWith("-"))
					{
					System.err.println("Unnown option: "+args[optind]);
					return;
					}
				else
					{
					break;
					}
				++optind;
				}
		
		if(dbHome==null)
			{
			System.err.println("Undefined dbHome");
			return ;
			}
		
		GuessBuild app=new GuessBuild();
		Transaction txn=null;
		ModelFactory factory=ModelFactory.newInstance();
		factory.setReadOnly(true);
		factory.setDbHome(dbHome);
		app.model=factory.open();
		
		if(optind==args.length)
			{
			LOG.info("Reading from stdin");
			app.run(txn,"<stdin>",new BufferedReader(new InputStreamReader(System.in)));
			}
		else 
			{
			while(optind<args.length)
				{
				String uri=args[optind++];
				LOG.info("Reading from file "+uri);
				BufferedReader in=IOUtils.openUrl(uri);
				app.run(txn,uri,in);
				in.close();
				}
			}
	
		app.close();
		
		LOG.info("Done.");
		}
}
